package com.united.ucts.common.plugin.security;

import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

/**
 * 自定义的SpringSecurity配置
 * 用于授权允许的特定白名单及认证过滤
 *
 * @author hudan
 * @version 1.0
 * @filename WebSecurityConfiguration.java
 * @copyright <a href="www.united.cn">www.united.cn</a>
 * @date 2019-10-10
 */
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    /**
     * 设置需要拦截的url路径、自定义jwt过滤器及出异常后的处理器
     * 用于处理用户登录请求、其他权限请求等
     * 此方法是整个spring-security最核心的方法
     *
     * @param httpSecurity spring-security的http安全管理器
     */
    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.authorizeRequests()
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                // 允许访问获取公钥接口
                .antMatchers("/rsa/publicKey").permitAll()
                // 允许访问swagger
                .antMatchers("/v2/api-docs").permitAll()
                // 测试的时候,允许oauth/token不认证
                .antMatchers("/oauth/token").permitAll()
                // 其他请求url都需要进行认证
                .anyRequest().authenticated();
    }

    /**
     * 定义授权管理器
     *
     * @return 授权管理器
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    /**
     * 配置密码的加密使用的算法
     * SpringSecurity定义的用于对密码加密的接口，目前使用的是BCryptPasswordEncoder
     *
     * @return 密码管理器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}